﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Text.RegularExpressions;
using System.Web;
using System.Xml;

namespace Twi.COMMON.Core
{
    /*
     * CopyRight:©2014 踏影软件开发工作室（Tyingsoft/Twilight）版权所有
     * Author:xuzhihong
     * Create Date: 2014-07-02
     * Description: 辅助类
     */
    public class TwiNetHelper
    {
        private static string TwiIpsCfgFile = TwiPathHelper.MapPath("~/Config/TwiIPs.config");
        private static XmlNodeList TwiIpsCfgNodes = default(XmlNodeList); //如果allow模式，存储
        private static TwiIpsControlModel TwiIpsCfgModel =TwiIpsControlModel.none;  //IP访问控制模式（none:不限定IP模式 allow:绑定允许模式 deny:限制模式）
        private static DateTime LastReadIPsCofgTime = DateTime.Now.AddMinutes(-6); //最后读取IP配置时间

        static TwiNetHelper() { 
           if(TwiPathHelper.ExistFile(TwiIpsCfgFile)){
               ReloadTwiIpsCfgNodes();
           }
        }

        /// <summary>
        /// 重新获取数据TwiIpsCfgNodes
        /// </summary>
        protected static void ReloadTwiIpsCfgNodes() {
            try
            {
                //5分钟才会重新读取一次配置文件，期间使用缓存
                if (DateTime.Now.Subtract(LastReadIPsCofgTime).TotalSeconds > 5*60)
                {
                    if (TwiPathHelper.ExistFile(TwiIpsCfgFile))
                    {
                        XmlDocument xmlDoc = new XmlDocument();
                        xmlDoc.Load(TwiIpsCfgFile);
                        XmlElement root = xmlDoc.DocumentElement;
                        var elements = root.ChildNodes.Cast<XmlNode>().Where(n => n.NodeType == XmlNodeType.Element);
                        XmlNode modelNode = elements.FirstOrDefault(n => n.Name == "model");
                        if (modelNode != null)
                        {
                            if (modelNode.InnerText == "allow")
                            {
                                TwiIpsCfgModel = TwiIpsControlModel.allow;
                                XmlNode allowNode = elements.FirstOrDefault(n => n.Name == "allowIPs");
                                TwiIpsCfgNodes = allowNode.ChildNodes;
                            }
                            else if (modelNode.InnerText == "deny")
                            {
                                TwiIpsCfgModel = TwiIpsControlModel.deny;
                                XmlNode denyNode = elements.FirstOrDefault(n => n.Name == "denyIPs");
                                TwiIpsCfgNodes = denyNode.ChildNodes;
                            }
                            else {
                                TwiIpsCfgModel = TwiIpsControlModel.none;
                            }
                        }
                    }
                    LastReadIPsCofgTime = DateTime.Now;
                }
            }
            catch (Exception ex){
                TwiLogHelper.Error("TwiNetHelper.ReloadTwiIpsCfgNodes读取TwiIPs.config配置文件异常:"+ex.Message);
            }
        }

        /// <summary>
        /// 检测是否为允许访问的IP
        /// </summary>
        /// <param name="ip">待检测的IP</param>
        /// <param name="msg">检测信息，成功或失败的信息</param>
        /// <param name="isThrowException">如果检测为不允许是否自动抛异常</param>
        /// <returns></returns>
        /// <remarks>
        /// msg中对应Code说明:
        /// none模式为：100  
        ///        Code=100:不限定IP模式(none)
        /// allow为：200
        ///        Code=200:当前IP被设置为允许访问
        ///        Code=201:当前IP不在允许的IP范围内
        /// deny为：300
        ///        Code=300:当前IP被设置为不允许访问
        ///        Code=301:当前IP不在限制的IP范围内
        /// </remarks>
        public static bool CheckIsAllowIp(string ip, ref string msg,bool isThrowException=false)
        {
            bool isAllow = false;
            ReloadTwiIpsCfgNodes();

            if (TwiIpsCfgModel == TwiIpsControlModel.none)
            {
                isAllow = true;
                msg = "Code=100:不限定IP模式(none)";
            }
            else
            {
                if (IsIP(ip)) //是否为正确格式的IP
                {
                    string commonIp = ip.Substring(0, ip.LastIndexOf('.')) + ".*"; //转成通配符IP，如192.168.0.*，只允许最后一位使用通配符
                    var elements = TwiIpsCfgNodes.Cast<XmlNode>().Where(m => m.NodeType == XmlNodeType.Element);
                    var findNode = elements.FirstOrDefault(m => m.Attributes["ip"].Value == ip || m.Attributes["ip"].Value == commonIp);
                    if (TwiIpsCfgModel == TwiIpsControlModel.allow)
                    {
                        if (findNode != null)
                        {
                            isAllow = true;
                            msg = "Code=200:当前IP被设置为允许访问";
                        }
                        else
                        {
                            isAllow = false;
                            msg = "Code=201:当前IP不在允许的IP范围内";
                        } 
                    }
                    else if (TwiIpsCfgModel == TwiIpsControlModel.deny)
                    {                        
                        if (findNode != null)
                        {
                            isAllow = false;
                            msg = "Code=300:当前IP被设置为不允许访问";
                        }
                        else {
                            isAllow = true;
                            msg = "Code=301:当前IP不在限制的IP范围内";
                        }                        
                    }                     
                }
                else
                {
                    isAllow = false;
                    msg = "未检测到正确格式的IP地址";
                }
            }
            //是否自动抛异常
            if (isThrowException) {
                throw new Exception(msg);
            }
            return isAllow;
        }

        /// <summary>
        /// 检测是否为允许访问的IP
        /// </summary>
        /// <param name="msg">检测信息，成功或失败的信息</param>
        /// <param name="isThrowException">如果检测为不允许是否自动抛异常</param>
        /// <returns></returns>
        public static bool CheckIsAllowIp(ref string msg,bool isThrowException=false) {
            return CheckIsAllowIp(GetIp(), ref msg,isThrowException);
        }

        /// <summary>
        /// 获取本地IP地址
        /// </summary>
        /// <returns></returns>
        public static string GetCurrentIp()
        {
            IPAddress[] ipAddress = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
            string ip = "";
            if (ipAddress.Length == 3)
            {
                ip = ipAddress[1].ToString();
            }
            else if (ipAddress.Length == 4)
            {
                ip = ipAddress[2].ToString();
            }
            else if (ipAddress.Length == 5)
            {
                ip = ipAddress[2].ToString();
            }
            else if (ipAddress.Length == 6)
            {
                ip = ipAddress[3].ToString();
                if (!IsIP(ip))
                {
                    ip = ipAddress[4].ToString();
                }
            }
            
            //还是不对，就直接赋值为空
            if (ip.Contains("::") || ip.Contains("%"))
            {
                ip = "";
            }
            return ip;
        }

        /// <summary>
        /// 是否IP地址
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        public static bool IsIP(string ip)
        {
            //判断是否为IP
            return Regex.IsMatch(ip, @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$");
        }

        /// <summary>
        /// 获取访问者IP地址
        /// </summary>
        /// <returns></returns>
        public static string GetIp()
        {
            string userIP;
            if (HttpContext.Current == null) {
                userIP = GetCurrentIp();
                if (userIP == "") {
                    userIP = DateTime.Now.ToString("HHmmss");
                }
                return userIP;
            }
            HttpRequest request = HttpContext.Current.Request;
            if (request == null)
            {
                userIP = "";
            }
            else
            {
                // 如果使用代理，获取真实IP
                if (request.ServerVariables["HTTP_X_FORWARDED_FOR"] != "")
                {
                    userIP = request.ServerVariables["REMOTE_ADDR"];
                }
                else
                {
                    userIP = request.ServerVariables["HTTP_X_FORWARDED_FOR"];
                }
                if (userIP == null || userIP == "")
                {
                    userIP = request.UserHostAddress;
                }
            }
            if (userIP.Contains("::") || userIP.Contains("%"))
            {
                userIP = GetCurrentIp();
                if (string.IsNullOrEmpty(userIP))
                {
                    userIP = DateTime.Now.ToString("HHmmss");
                }
            }
            return userIP;
        }

        /// <summary>
        /// 获取浏览器版本相关信息
        /// </summary>
        /// <returns></returns>
        public static string GetHttpUserAgent() {
            if (HttpContext.Current == null)
            {
                return null;
            }
            HttpRequest request = HttpContext.Current.Request;
            return request.ServerVariables["HTTP_USER_AGENT"];
        }
    }

    /// <summary>
    /// IP访问控制模式
    /// </summary>
    public enum TwiIpsControlModel {
        none,   //不限定IP模式
        allow,  //允许绑定IP模式
        deny
    }
}
